4.8. Aliohjelmat ja niiden parametrit
Aliohjelmalla (engl. procedure, function) tarkoitetaan jotain tiettyä komentojen ryhmää. Aliohjelmalle annetaan nimi, jotta sitä voidaan kutsua myöhemmin ohjelmassa. Kun aliohjelmaa kutsutaan, suor itetaan kaikki aliohjelman ryhmässä olleet komennot. Jos esimerkiksi ohjelmassa tarvitaan jotain toimintoa useammin kuin kerran, kannattaa siitä tehdä aliohjelma. Aliohjelmaa kutsutaan (eli käytetään) ohjelmassa samalla tavalla kuin mitä tahansa Tcl-komentoa. Aliohjelma määritellään komennolla proc, jolle annetaan parametreina aliohjelman nimi, aliohjelmalle vietävät parametrit ja kaarisulkeissa komentojen ry hmä.
Esimerkissä
proc laske_summa {eka_luku toka_luku} {
set summa [expr $eka_luku + $toka_luku]
return $summa
}
on esitelty aliohjelma laske_summa, joka laskee yhteen parametreina saamansa luvut. Aliohjelma palauttaa laskemansa summan komennolla return. Aliohjelman suoritus pä&au ml;ttyy yleensä return-komennon suorittamiseen, joten sitä voidaan käyttää aliohjelman suorituksen katkaisemiseen halutusta kohdasta. Return-komennon ei siis tarvitse olla ki rjoitettuna viimeiseksi komennoksi. Itse asiassa return-komentoa ei tarvitse olla aliohjelmassa lainkaan. Kun aliohjelman kaikki komennot on suoritettu, loppuu aliohjelman suoritus ja se palauttaa arvonaan viimeisen komentonsa palauttaman arvon. Yllä olevan esimerkin aliohjelma voidaan siis myös kirjoittaa ilman return-komentoa:
proc laske_summa {eka_luku toka_luku} {
expr $eka_luku + $toka_luku
}
Usein on tilanteita, jolloin aliohjelma tekee vain jonkin tietyn toiminnon ilman, että siitä tarvitaan mitään erityistä palautusarvoa (esimerkiksi listan alkioiden kääntäminen kää nteiseen järjestykseen). Joskus kuitenkin aliohjelman tarkoituksena on nimenomaan palauttaa jokin arvo, kuten edellisen esimerkin laske_summa-aliohjelmalla.
Aliohjelmaa kutsutaan siis kuten mitä tahansa komentoa. Seuraavassa esimerkissä on kutsuttu laske_summa-aliohjelmaa:
set yhteensa [laske_summa 2 5]
=> 7
Aliohjelmaa laske_summa kutsuttaessa parametreina annetut arvot (2 ja 5) sijoitetaan järjestyksessä aliohjelman esittelyssä annettuihin muuttujiin (eka_luku ja toka_luku), jonka jälkeen niitä voidaan aliohjelman suorituksen aikana käyttää tavallisten muuttujien tavoin (esim. $eka_luku). Jotta aliohjelmaa voidaan kutsua, on se esitelt&aum l;vä ennen käyttöä. Tämä tarkoittaa sitä, että aliohjelma on fyysisesti kirjoitettava koodiin ennen kuin sitä ensimmäisen kerran kutsutaan.
Kaikki muuttujat, jotka luodaan aliohjelmassa, häviävät automaattisesti aliohjelman suorituksen loputtua. Aliohjelmassa luodut muuttujat ovat siis paikallisia muuttujia, joten niihin ei voi viitata missään alioh jelman ulkopuolella. Vastaavasti on olemassa globaaleja muuttujia, joiden arvoon voi niiden luomisen jälkeen viitata missä tahansa kohdassa ohjelmaa, ja ne "elävät" koko ohjelman suorituksen loppuun asti. Jotta aliohjelmissa voidaan vi itata globaaleihin muuttujiin, on aliohjelmalle kerrottava ensin, mitkä muuttujat ovat globaaleja. Tämä tehdään global-komennolla, jolle annetaan parametrina vain muuttujan nimi. Jos globaalia muuttujaa ei ollut ennestään olemassa, luo global-komento sen. Seuraavan esimerkin prokkis-aliohjelma muuttaa globaalin muuttujan joka_paikan_muuttuja arvoa.
global joka_paikan_muuttuja
set joka_paikan_muuttuja 99
proc prokkis { eka } {
;# aliohjelman sisällä pitää globaalit muuttujat esitellä
;# globaaleiksi
global joka_paikan_muuttuja
set joka_paikan_muuttuja $eka
}
prokkis 77
set joka_paikan_muuttuja
=> 77
Jos aliohjelmassa ei olisi ollut riviä global joka_paikan_muuttuja, olisi aliohjelmassa vain laitettu aliohjelman paikalliseen muuttujaan joka_paikan_muuttuja arvo, jol loin saman niminen globaali muuttuja olisi pysynyt koskemattomana. Globaalien muuttujien kanssa kannattaa olla huolellinen, jotta muistaa tarvittaessa esitellä ne aliohjelman alussa.
Aliohjelmalle ei ole pakko määritellä parametreja ollenkaan, jolloin aliohjelman esittelyssä jätetään nimen jälkeiset sulut yksinkertaisesti tyhjiksi.
global globbis
set globbis 55
proc prokkis_nollaa {} {
global globbis
set globbis 0
}
prokkis_nollaa
set globbis
=>0
Kun aliohjelmaa kutsutaan, on parametreja annettava korkeintaan se määrä, joka on aliohjelman esittelyssä määrätty. Aliohjelmalla voi kuitenkin olla parametreja, joille annetaan oletusarvot. T&a uml;llöin oletusarvon omaavaa parametria ei ole pakko antaa aliohjelmaa kutsuttaessa. Jos oletusparametrille ei anneta arvoa aliohjelmaa kutsuttaessa, laitetaan vastaavan muuttujan arvoksi oletusarvo. Oletusparametri ja sen oletusarvo laitetaan param etrilistaan kaarisulkeissa. Esimerkin
proc prokkis_nollaa { {nollaus_arvo 0} } {
global globbis
set globbis $nollaus_arvo
}
prokkis_nollaa
set globbis
=>0
prokkis_nollaa 9999999
set globbis
=>9999999
prokkis_nollaa 3 9
=> VIRHEILMOITUS ! (Liian monta parametria.)
prokkis_nollaa-aliohjelmaa voidaan kutsua joko ilman parametreja tai yhdellä parametrilla. Jos parametreja innostuu laittamaan aliohjelman kutsussa liikaa, antaa tulkki virheilmoituksen näytölle.
Kun aliohjelmalle annetaan parametrina jonkin muuttujan arvo, välittyy se arvoparametrina aliohjelmalle (engl. passing by value). Jos halutaan, että aliohjelmassa tehdyt muutokset aliohjelman parametriin vaikuttavat suo raan alkuperäiseen muuttujaan, on muuttujan nimi vietävä aliohjelmalle viiteparametrina (engl. passing by reference) [WEL97W]. Saman voisi tehdä globaalien muuttujien avulla, jolloin aliohjelmassa tehdyt muutokset globaaliin muu ttujaan näkyisivät myös aliohjelman ulkopuolelle. Joskus on kuitenkin tarkoituksenmukaisempaa muuttaa aliohjelmassa kutsuvan aliohjelman paikallista muuttujaa. Seuraavan esimerkin aliohjelma prokkis_turha_homma e i tee ohjelman suorituksen kannalta mitään järkevää. Sen sijaan aliohjelma prokkis_viite muuttaa parametrinaan saamansa muuttujan arvoa.
proc prokkis_turha_homma { para1 } {
set para1 888
;#Yllä laitetaan arvo aliohjelman paikalliseen
;#muuttujaan
}
set koe 33
prokkis_turha_homma koe
set koe
=>33
proc prokkis_viite { para1 } {
upvar $para1 viite_muuttuja
set viite_muuttuja 888
;#Yllä laitetaan arvo aliohjelmalle parametrina
;#annettuun muuttujaan
}
set koe 33
prokkis_viite koe
set koe
=>888
Viiteparametri määritellään aliohjelmassa esimerkin mukaisesti komennolla upvar. Sille annetaan kaksi parametria. Ensimmäinen on sen aliohjelman parametrin arvo ($para1), johon viite luodaan. Toinen on paikallinen viitemuuttuja (viite_muuttuja). upvar-komennon jälkeen kaikki viittaukset viitemuuttujaan kohdistuvat alkuperäiseen paramet rina annettuun muuttujaan.
Taulukoita käsiteltäessä on muistettava, että taulukkoa ei voi antaa tavallisena arvoparametrina. Jotta aliohjelmassa voidaan käsitellä taulukon alkioita, on sen oltava joko globaali taulukko tai se on viet ävä viiteparametrina aliohjelmalle. Viiteparametreja käytettäessä on oltava tarkkana, ettei muuta sellaisen muuttujan arvoa, jonka on määrä pysyä muuttumattomana koko ohjelman ajan (vertaa static-muuttuj a C-kielessä). Tcl-kielessä ei ole olemassa suoraan määritelmää muuttujalle, jonka arvoa ei voi ensimmäisen kerran jälkeen muuttaa (engl. static variable), joten ohjelmoijan on itse huolehdittava tällais en muuttujan muuttumattomuudesta.